package game.components;

import java.awt.Point;
import java.util.Stack;

public class RuleOfGame {
	private AppUtilities appUtilities;
	private int count = 0;

	// point mask
	protected final Point maskTL = new Point(-1, -1); // top left
	protected final Point maskTR = new Point(1, -1); // top right
	protected final Point maskTT = new Point(0, -1); // top
	protected final Point maskBL = new Point(-1, 1); // bottom left
	protected final Point maskBR = new Point(1, 1); // bottom right
	protected final Point maskBB = new Point(0, 1); // bottom
	protected final Point maskLL = new Point(-1, 0); // left
	protected final Point maskRR = new Point(1, 0); // right

	public RuleOfGame(AppUtilities appUtilities) {
		this.appUtilities = appUtilities;
	}

	protected void resetRule() {

	}

	protected Stack<Point> getMoveCollection(Player player) {
		return player.getMoveCollection();
	}

	protected Stack<Point> getPlayer1Moving() {
		return this.getMoveCollection(appUtilities.getPlayer1());
	}

	protected Stack<Point> getPlayer2Moving() {
		return this.getMoveCollection(appUtilities.getPlayer2());
	}

	public boolean checkExistedPoint(Point p) {
		boolean flag1 = this.getPlayer1Moving().contains(p);
		boolean flag2 = this.getPlayer2Moving().contains(p);

		return (flag1 || flag2);
	}

	public Player getWiner() {
		Player currenPlayer = appUtilities.getTurnOfPlayer();

		// check player 1
		Stack<Point> allMoving = getMoveCollection(currenPlayer);
		if (checkWinHelper2(allMoving)) {
			appUtilities.setWinner(currenPlayer);
			return currenPlayer;
		}

		appUtilities.setWinner(null);

		return null;
	}

	protected boolean checkWinHelper2(final Stack<Point> allMoving) {

		if (allMoving.isEmpty()) {
			return false;
		}

		boolean out = false;
		Point[] points = new Point[2];
		Point p = allMoving.peek();

		// #1 check LL RR -- --
		points[0] = maskLL;
		points[1] = maskRR;
		out = checkWinHelper2(p, points, allMoving);
		if (out) {
			return out;
		}

		// #2 check TT BB || ||
		points[0] = maskTT;
		points[1] = maskBB;
		out = checkWinHelper2(p, points, allMoving);
		if (out) {
			return out;
		}

		// #3 check TL BR \\ \\
		points[0] = maskTL;
		points[1] = maskBR;
		out = checkWinHelper2(p, points, allMoving);
		if (out) {
			return out;
		}

		// #4 check TR BL // //
		points[0] = maskTR;
		points[1] = maskBL;
		out = checkWinHelper2(p, points, allMoving);
		if (out) {
			return out;
		}

		return out;
	}

	protected boolean checkWinHelper2(final Point p, Point[] masks,
			final Stack<Point> allMoving) {

		Point[] points = { new Point(p), new Point(p) };
		points[0].translate(masks[0].x, masks[0].y);
		points[1].translate(masks[1].x, masks[1].y);

		// count itself
		this.count++;

		// count up 1
		while (allMoving.contains(points[0])) {
			points[0].translate(masks[0].x, masks[0].y);
			this.count++;
		}
		// count up 2
		while (allMoving.contains(points[1])) {
			points[1].translate(masks[1].x, masks[1].y);
			this.count++;
		}

		if (this.count == 5
				&& (!allMoving.contains(points[0]) || !allMoving
						.contains(points[0]))) {
			this.count = 0;
			return true;
		}

		count = 0;
		return false;
	}

	public void setAppUtilities(AppUtilities appUtilities) {
		this.appUtilities = appUtilities;
	}
}
